# include "EventListener.h"

# include "Game.h"
# include "Renderer.h"
# include "AI.h"
# include "GUI.h"

# include "World.h"
# include "Hero.h"

CEGUI::MouseButton convertButton( OIS::MouseButtonID buttonID)
{
	switch ( buttonID )
	{
	case OIS::MB_Left:
	return CEGUI::LeftButton;

	case OIS::MB_Right:
	return CEGUI::RightButton;

	case OIS::MB_Middle:
	return CEGUI::MiddleButton;

	default:
	return CEGUI::LeftButton;
	}
}

EventListener::EventListener( Game* game) : Module( game)
{

}

EventListener::~EventListener()
{

}

void EventListener::setWindow( Ogre::RenderWindow* window)
{
	myWindow = window;
}

void EventListener::setWorld( World* world)
{
	myWorld = world;
	myHero = myWorld->getHero();
}

OIS::Mouse* EventListener::getMouse()
{
	return myMouse;
}

void EventListener::init( Renderer* renderer, GUI* gui, AI* ai)
{
	myRenderer = renderer;
	myGUI = gui;
	myAI = ai;

	Ogre::LogManager::getSingletonPtr()->logMessage( "*** Initializing OIS ***");
    OIS::ParamList plTmp;
    size_t windowHndTmp = 0;
    std::ostringstream windowHndStrTmp;

    myRenderer->getWindow()->getCustomAttribute( "WINDOW", &windowHndTmp);
    windowHndStrTmp << windowHndTmp;
    plTmp.insert( std::make_pair( std::string("WINDOW"), windowHndStrTmp.str()));

    myInputManager = OIS::InputManager::createInputSystem( plTmp);

    myKeyboard = static_cast<OIS::Keyboard*>( myInputManager->createInputObject( OIS::OISKeyboard, true ));
    myMouse = static_cast<OIS::Mouse*>( myInputManager->createInputObject( OIS::OISMouse, true ));

    myMouse->setEventCallback(this);
    myKeyboard->setEventCallback(this);

	myState = MENU_STATE;
}

void EventListener::oneFrame()
{
	handleEvents();

	myKeyboard->capture();
	myMouse->capture();
}

bool EventListener::keyPressed( const OIS::KeyEvent& evt)
{
	CEGUI::System& systemTmp = CEGUI::System::getSingleton();
	systemTmp.injectKeyDown( evt.key);
	systemTmp.injectChar( evt.text);

	switch ( myState )
	{
		case MENU_STATE:
		break;
		
		case GUI_STATE:
		break;

		case GAME_STATE:
		{
			if ( evt.key == OIS::KC_ESCAPE )
			{
				Event evtTmp;
				evtTmp.message = CREATE_GAME_MENU;

				myGame->receiveEvent( evtTmp);
			}

			if ( evt.key == OIS::KC_W )
			{
				myHero->zoom();
			}

			if ( evt.key == OIS::KC_S )
			{
				myHero->deZoom();
			}

			if ( evt.key == OIS::KC_A )
			{
				myHero->rotateCounterClock();
			}

			if ( evt.key == OIS::KC_D )
			{
				myHero->rotateClock();
			}

			if ( evt.key == OIS::KC_K )
			{
				Event evtTmp;
				evtTmp.message = OPEN_COMPETENCE;

				myGame->receiveEvent( evtTmp);
			}

			if ( evt.key == OIS::KC_I )
			{
				Event evtTmp;
				evtTmp.message = OPEN_INVENTORY;

				myGame->receiveEvent( evtTmp);
			}

			if ( evt.key == OIS::KC_L )
			{
				Event evtTmp;
				evtTmp.message = OPEN_QUEST;

				myGame->receiveEvent( evtTmp);
			}
		}
		break;
	}
	
	return true;
}

bool EventListener::keyReleased( const OIS::KeyEvent& evt)
{
	CEGUI::System::getSingleton().injectKeyUp( evt.key);

	switch ( myState )
	{
		case MENU_STATE:
		break;
		
		case GUI_STATE:
		if ( evt.key == OIS::KC_ESCAPE )
		{
			Event evtTmp;

			evtTmp.message = CLOSE_GUI_WINDOW;
			myGUI->receiveEvent( evtTmp);
		}
		break;
		
		case GAME_STATE:
		if ( evt.key == OIS::KC_W || evt.key == OIS::KC_S )
		{
			myHero->stopZoom();
		}

		if ( evt.key == OIS::KC_A || evt.key == OIS::KC_D )
		{
			myHero->rotateStop();
		}
		break;
	}

	return true;
}

bool EventListener::mouseMoved( const OIS::MouseEvent& evt)
{
	CEGUI::System& systemTmp = CEGUI::System::getSingleton();
	systemTmp.injectMouseMove( evt.state.X.rel, evt.state.Y.rel);

	if ( evt.state.Z.rel )
	{
		systemTmp.injectMouseWheelChange( evt.state.Z.rel / 120.0f);
	}

	switch ( myState )
	{
		case GAME_STATE:
		{
			Event evtTmp;

			evtTmp.message = REQUEST;
			evtTmp.x = evt.state.X.abs;
			evtTmp.y = evt.state.Y.abs;

			myAI->receiveEvent( evtTmp);
		}
	}

	return true;
}

bool EventListener::mousePressed( const OIS::MouseEvent& evt, OIS::MouseButtonID id)
{
	CEGUI::System::getSingleton().injectMouseButtonDown( convertButton( id));
	
	switch ( myState )
	{
		case MENU_STATE:	
		break;
		
		case GUI_STATE:
		break;

		case GAME_STATE:
		{
			if ( id == OIS::MouseButtonID::MB_Left )
			{
				Event evtTmp;

				evtTmp.message = MOUSE_LEFT_CLICKED;
				evtTmp.x = evt.state.X.abs;
				evtTmp.y = evt.state.Y.abs;

				myAI->receiveEvent( evtTmp);
			}
		}
	}
	
	return true;
}

bool EventListener::mouseReleased( const OIS::MouseEvent& evt, OIS::MouseButtonID id)
{
	CEGUI::System::getSingleton().injectMouseButtonUp( convertButton( id));
	
	return true;
}

void EventListener::handleEvents()
{
	while ( !myEvents.empty() )
	{
		Event evtTmp = myEvents.front();
		myEvents.pop();

		if ( evtTmp.message == NEW_GAME )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == CREATE_GAME_MENU )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == RETURN_GAME )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == OPEN_INVENTORY )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == CLOSE_INVENTORY )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == OPEN_COMPETENCE )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == CLOSE_COMPETENCE )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == RETURN_MENU )
		{
			myState = MENU_STATE;
		}

		if ( evtTmp.message == OPEN_TALK )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == CLOSE_GUI_WINDOW )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == CLOSE_TALK )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == OPEN_QUEST )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == CLOSE_QUEST )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == HERO_DEATH )
		{
			myState = GUI_STATE;
		}
	}
}